#pragma once
#include<assert.h>

namespace gugu
{
	template<class T>
	struct ListNode
	{
		ListNode<T>* _prve;
		ListNode<T>* _next;
		T _data;

		ListNode(const T& val = T())
			:_prve(nullptr)
			, _next(nullptr)
			, _data(val)
		{}
	};
	template<class T>
	struct ListIteratoe
	{
		typedef ListNode<T> Node;

		Node* _node;

		ListTterator(Node* node)
			:_node(node)
		{}

		bool operator!=(const Node& node)
		{
			return *this != node;
		}

	};

	template<class T>
	class list
	{

	public:
		typedef ListNode<T> Node;
		typedef ListIteratoe<T> iterator;

		iterator& end()
		{
			return _head->_next;
		}
		iterator& begin()
		{
			return _head;
		}



		void empty_init()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prve = _head;
		}
		

		list()
		{
			empty_init();
		}
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

		void clear()
		{
			while (size)
			{
				Node* prve = _head->_prve;
				prve->_prve->_next = _head;
				_head->_prve = prve->_prve;
				delete prve;
				prve->_next = nullptr;
				prve->_prve = nullptr;
				size--;
			}
		}

		void push_back(const T& val)
		{
			Node* newNode = new Node;
			newNode->_data = val;
			Node* prve = _head->_prve;
			prve->_next = newNode;
			newNode->_prve = prve;
			newNode->_next = _head;
			_head->_prve = newNode;

			_size++;
		}
		void push_front(const T& val)
		{
			Node* newNode = new Node;
			newNode->_data = val;

			Node* next = _head->_next;
			next->_prve = newNode;
			newNode->_next = next;
			newNode->_prve = _head;
			_head->_next = newNode;

			_size++;
		}

	public:
		Node* _head;
		size_t _size;
	};

	void test_list1()
	{
		list<int> l1;
		l1.push_back(1);
		l1.push_back(2);
		l1.push_back(3);
		l1.push_back(4);
		l1.push_back(5);

		l1.push_front(0);

		list<int>::iterator it = l1.begin();
		while (it != l1.end())
		{
			cout << *it << " ";
		}
		cout << endl;

	}
}